/*=============================================================================
*
*   Copyright (C) 2020 All rights reserved.
*
*   Filename:		point_impl.hpp
*
*   Author: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Date: 2020-02-26 17:36
*
*   Last Editors: Wang Zhecheng - wangzhecheng@yeah.net
*
*   Last modified:	2020-03-06 17:02
*
*   Description:
*
=============================================================================*/
#ifndef POINTIMPL_H
#define POINTIMPL_H

#include "../../traits.hpp"
#include "../../types.hpp"
#include "../../util/debugger.hpp"

namespace geoxfem {
namespace geometry {

template <size_t dim>
struct Point;

template <size_t dim>
struct point_impl {
  /*constructors and destructor{{{*/

  /**
   * @brief point_impl default constructor.
   */
  point_impl() {
    GEOXFEM_NOT_IMPLEMENTED();
  }
  /**
   * @brief point_impl constructor with three dimension. Only works in
   * 3-dimension.
   *
   * @param
   * @param
   * @param
   */
  point_impl(const _real&, const _real&, const _real& = 0) {
    GEOXFEM_NOT_IMPLEMENTED();
  }
  /**
   * @brief point_impl constructor with Eigen Vector.
   *
   * @param rhs
   */
  point_impl(const Eigen::Matrix<_real, dim, 1>& rhs) : m_coord{rhs} {}
  point_impl(const point_impl<dim>&) = default;
  point_impl(point_impl<dim>&&)      = default;
  ~point_impl()                      = default;
  point_impl& operator=(const point_impl<dim>&) = default;
  point_impl& operator=(point_impl<dim>&&) = default;
  /*}}}*/
  /*misc{{{*/
  /**
   * @brief operator==
   *
   * @param rhs
   *
   * @return
   */
  bool operator==(const point_impl<dim>& rhs) {
    return m_coord == rhs.m_coord;
  }
  /*}}}*/

  friend struct Point<dim>;

private:
  Eigen::Matrix<_real, dim, 1> m_coord;
};

/*specialization{{{*/
template <>
point_impl<2>::point_impl() {
  m_coord << 0, 0;
}
template <>
point_impl<2>::point_impl(const _real& _x, const _real& _y, const _real&) {
  m_coord << _x, _y;
}
template <>
point_impl<3>::point_impl() {
  m_coord << 0, 0, 0;
}
template <>
point_impl<3>::point_impl(const _real& _x, const _real& _y, const _real& _z) {
  m_coord << _x, _y, _z;
}
/*}}}*/

}  // namespace geometry

template <size_t dim>
struct traits::dimension<geometry::point_impl<dim>> {
  static constexpr size_t value = dim;
};
}  // namespace geoxfem

#endif /* POINTIMPL_H */
